#!/bin/env php
<?php
/*
根据给定的参数和已知的时间序列文件，使用AR模型预测数据未来的分布
使用方法：
php arpredict.php -i input.csv -p 0.9,-0.8,0.6 -s 0.5
*/

function echoHelpMessage() {
    echo <<<HELPINFO
根据给定的参数和已知的时间序列文件，使用AR模型预测数据未来的分布
使用方法：
php arpredict.php -i input.csv -p 0.9,-0.8,0.6 -s 0.5 -t 10
-i 输入文件
-p AR模型参数
-s 噪声标准差
-t 预测个数

HELPINFO;
}

function checkCommandParams(string $paramName, array $commandPrams) {
    if (!isset($commandPrams[$paramName])) {
        echo '参数' . $paramName . '必填' . PHP_EOL;
        echoHelpMessage();
        exit(-1);
    }
}

$commandPrams = getopt('i:p:s:t:');
checkCommandParams('i', $commandPrams);
checkCommandParams('p', $commandPrams);
checkCommandParams('s', $commandPrams);
checkCommandParams('t', $commandPrams);
if (!is_file($commandPrams['i'])) {
    echo '文件' . $commandPrams['i'] . '不存在' . PHP_EOL;
    exit(-1);
}
if ($commandPrams['s'] <= 0) {
    echo '参数-s必须大于0' . PHP_EOL;
    exit(-1);
}
if ($commandPrams['t'] <= 0) {
    echo '参数-t必须大于0' . PHP_EOL;
    exit(-1);
}
$paramsAR = explode(',', $commandPrams['p']);
$sequence = [];
$fp = fopen($commandPrams['i'], 'rb');
if (false === $fp) {
    echo '打开文件' . $commandPrams['i'] . '失败' . PHP_EOL;
    exit(-1);
}
while (true) {
    $row = fgetcsv($fp);
    if (empty($row)) {
        break;
    }
    $sequence[] = floatval($row[0]);
}
fclose($fp);
$needs = [];
for ($i = count($sequence) - count($paramsAR); $i < count($sequence); $i++) {
    $needs[] = $sequence[$i];
}
unset($sequence);
$exps = [];
$vars = [];
for ($i = 0; $i < $commandPrams['t']; $i++) {
    $needs[count($paramsAR) + $i] = 0;
    for ($j = 0; $j < count($paramsAR); $j++) {
        $needs[count($paramsAR) + $i] += $paramsAR[$j] * $needs[count($paramsAR) + $i - $j - 1];
    }
    $exps[$i] = $needs[count($paramsAR) + $i];
    $vars[$i] = ($vars[$i - 1] ?? 0) + $commandPrams['s'] * $commandPrams['s'];
}
for ($i = 0; $i < $commandPrams['t']; $i++) {
    echo ($i + 1) . ',' . sprintf('%.9f', round($exps[$i], 9)) . ',' . sprintf('%.9f', round($exps[$i] - 2 * sqrt($vars[$i]), 9)) . ',' . sprintf('%.9f', round($exps[$i] + 2 * sqrt($vars[$i]), 9)) . PHP_EOL;
}
